API Gateway 생성 시 발생하는 No ‘Access-Control-Allow-Origin’ 문제 해결

API Gateway 생성 시 발생하는 No ‘Access-Control-Allow-Origin’ 문제 해결

Clock Icon2024.6.26

안녕하세요 클래스메소드 김재욱(Kim Jaewook) 입니다. 이번에는 API Gateway 생성 시 발생하는 No ‘Access-Control-Allow-Origin’ 문제를 해결하는 방법에 대해서 정리해 봤습니다.

문제 발생

Amplify를 통해 웹 사이트를 배포하고 있는 환경에서 No ‘Access-Control-Allow-Origin 에러가 발생했습니다.

API Gateway와 Lambda는 문제없이 연결된 상태입니다.

하지만, API Gateway의 엔드포인트로 접근해 보면 에러가 발생하고 있는 것을 확인할 수 있습니다.

API Gateway와 Lambda 사이에서 제대로 연동이 이루어지지 않은 것 같습니다.

문제 해결

CORS 즉, Cross-Origin Resource Sharing는 오리진 간 리소스를 공유하는 역할을 수행합니다. 이번에 구축한 웹 호스팅을 수행하는 사이트는 AWS Amplify에 JS, HTML 파일을 업로드하며, 이 파일에는 Ajax 등을 사용하여 API Gateway의 API에 접근을 수행하는 코드를 담고 있습니다. 여기서 Ajax 등으로 다른 오리진(API Gateway의 API)으로 접근하기 위해서는 CORS를 활성화할 필요가 있습니다.

기본적으로 스키마, 호스트 및 포트가 모두 일치하는 경우에만 동일한 오리진이라고 말할 수 있습니다. 그렇다면 여기서 말하는 동일한 오리진은 무엇일까요? 예시를 들어보면 다음과 같습니다.

  • http://jaewook.com/app1/index.html
  • http://jaewook.com/app2/index.html
  • http://Jaewook.com:80
  • http://jaewook.com

스키마, 호스트 및 포트가 전부 동일하기 때문에 동일한 오리진이라고 볼 수 있습니다. 반대로 다른 오리진에 대한 예시를 살펴보면 다음과 같습니다.

  • http://jaewook.com/app1/index.html
  • https://jaewook.com/app2/index.html
  • http://www.jaewook.com/app2/index.html
  • http:/jaewook.com/app2/index.html:8080

확인해 보면, 스키마, 호스트, 포트가 각기 다르므로 동일한 오리진이 아니라는 것을 한 번에 확인할 수 있습니다. 보다 명확한 이유는 아래에서 설명하고 있습니다.

  • 보안상의 이유로 브라우저는 스크립트에 의한 오리진 간 HTTP 요청을 제한하고 있으며 JavaScript의 XMLHttpRequests, Fetch 등의 API는 동일한 오리진 정책을 따릅니다.
  • 동일한 오리진 정책에 의해, 보안은 지켜지지만, Ajax등의 통신을 이용한 경우 등 유연성이 부족하다.
  • 웹 통신의 전제로서 동일한 오리진 접속, 다른 오리진에 액세스하는 경우는 CORS에 의해 통신을 실시할 필요가 있다.

CloudFormation을 사용하는 경우 API Gateway에 다음 코드를 삽입합니다.

        IntegrationResponses:
            - StatusCode: 200
              ResponseParameters:
                method.response.header.Access-Control-Allow-Origin: "'*'"
                method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
                method.response.header.Access-Control-Allow-Methods: "'POST,OPTIONS'"
      MethodResponses:
        - StatusCode: 200
          ResponseParameters:
            method.response.header.Access-Control-Allow-Origin: true
            method.response.header.Access-Control-Allow-Headers: true
            method.response.header.Access-Control-Allow-Methods: true

각 메소드에 CORS를 활성화시키는 코드를 삽입합니다.

 ApiGatewayOptionsMethod:
    Type: AWS::ApiGateway::Method
    Properties:
      AuthorizationType: NONE
      HttpMethod: OPTIONS
      ResourceId: 
        Fn::GetAtt: [ApiGatewayRestApi, RootResourceId]
      RestApiId: !Ref ApiGatewayRestApi
      Integration:
        IntegrationHttpMethod: OPTIONS
        Type: MOCK
        IntegrationResponses:
          - StatusCode: 200
            ResponseParameters:
              method.response.header.Access-Control-Allow-Origin: "'*'"
              method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
              method.response.header.Access-Control-Allow-Methods: "'GET,POST,OPTIONS'"
        PassthroughBehavior: WHEN_NO_TEMPLATES
        RequestTemplates:
          application/json: "{\"statusCode\": 200}"
      MethodResponses:
        - StatusCode: 200
          ResponseParameters:
            method.response.header.Access-Control-Allow-Origin: true
            method.response.header.Access-Control-Allow-Headers: true
            method.response.header.Access-Control-Allow-Methods: true

이어서 옵션 메소드를 추가해주면 됩니다.

콘솔 화면에서의 CORS 설정은 다음 블로그를 참고해 주세요.

CORS를 설정하고 다시 웹 사이트에 접근해 보면, 성공적으로 데이터가 불러와지는 것을 확인할 수 있습니다.

본 블로그 게시글을 읽고 궁금한 사항이 있으신 분들은 kis2702@naver.com로 보내주시면 감사하겠습니다.

この記事をシェアする

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.